---
title: "Reference: Workflow Class | Building Workflows | Kastrax Docs"
description: Documentation for the Workflow class in Kastrax, which enables you to create state machines for complex sequences of operations with conditional branching and data validation.
---

# Workflow Class ✅

The Workflow class enables you to create state machines for complex sequences of operations with conditional branching and data validation.

```ts copy
import { Workflow } from "@kastrax/core/workflows";

const workflow = new Workflow({ name: "my-workflow" });
```

## API Reference ✅

### Constructor

<PropertiesTable
  content={[
    {
      name: "name",
      type: "string",
      description: "Identifier for the workflow",
    },
    {
      name: "logger",
      type: "Logger<WorkflowLogMessage>",
      isOptional: true,
      description: "Optional logger instance for workflow execution details",
    },
    {
      name: "steps",
      type: "Step[]",
      description: "Array of steps to include in the workflow",
    },
    {
      name: "triggerSchema",
      type: "z.Schema",
      description: "Optional schema for validating workflow trigger data",
    },
  ]}
/>

### Core Methods

#### `step()`

Adds a [Step](./step-class.mdx) to the workflow, including transitions to other steps. Returns the workflow instance for chaining. [Learn more about steps](./step-class.mdx).

#### `commit()`

Validates and finalizes the workflow configuration. Must be called after adding all steps.

#### `execute()`

Executes the workflow with optional trigger data. Typed based on the [trigger schema](./workflow.mdx#trigger-schemas).

## Trigger Schemas ✅

Trigger schemas validate the initial data passed to a workflow using Zod.

```ts showLineNumbers copy
const workflow = new Workflow({
  name: "order-process",
  triggerSchema: z.object({
    orderId: z.string(),
    customer: z.object({
      id: z.string(),
      email: z.string().email(),
    }),
  }),
});
```

The schema:

- Validates data passed to `execute()`
- Provides TypeScript types for your workflow input

## Validation ✅

Workflow validation happens at two key times:

### 1. At Commit Time

When you call `.commit()`, the workflow validates:

```ts showLineNumbers copy
workflow
  .step('step1', {...})
  .step('step2', {...})
  .commit(); // Validates workflow structure
```

- Circular dependencies between steps
- Terminal paths (every path must end)
- Unreachable steps
- Variable references to non-existent steps
- Duplicate step IDs

### 2. During Execution

When you call `start()`, it validates:

```ts showLineNumbers copy
const { runId, start } = workflow.createRun();

// Validates trigger data against schema
await start({
  triggerData: {
    orderId: "123",
    customer: {
      id: "cust_123",
      email: "invalid-email", // Will fail validation
    },
  },
});
```

- Trigger data against trigger schema
- Each step's input data against its inputSchema
- Variable paths exist in referenced step outputs
- Required variables are present

## Workflow Status ✅

A workflow's status indicates its current execution state. The possible values are:

<PropertiesTable
  content={[
    {
      name: "CREATED",
      type: "string",
      description: "Workflow instance has been created but not started"
    },
    {
      name: "RUNNING",
      type: "string",
      description: "Workflow is actively executing steps"
    },
    {
      name: "SUSPENDED",
      type: "string",
      description: "Workflow execution is paused waiting for resume"
    },
    {
      name: "COMPLETED",
      type: "string",
      description: "All steps finished executing successfully"
    },
    {
      name: "FAILED",
      type: "string",
      description: "Workflow encountered an error during execution"
    }
  ]}
/>

### Example: Handling Different Statuses

```typescript showLineNumbers copy
const { runId, start, watch } = workflow.createRun();

watch(async ({ status }) => {
  switch (status) {
    case "SUSPENDED":
      // Handle suspended state
      break;
    case "COMPLETED":
      // Process results
      break;
    case "FAILED":
      // Handle error state
      break;
  }
});

await start({ triggerData: data });
```

## Error Handling ✅

```ts showLineNumbers copy
try {
  const { runId, start, watch, resume } = workflow.createRun();
  await start({ triggerData: data });
} catch (error) {
  if (error instanceof ValidationError) {
    // Handle validation errors
    console.log(error.type); // 'circular_dependency' | 'no_terminal_path' | 'unreachable_step'
    console.log(error.details); // { stepId?: string, path?: string[] }
  }
}
```

## Passing Context Between Steps ✅

Steps can access data from previous steps in the workflow through the context object. Each step receives the accumulated context from all previous steps that have executed.

```typescript showLineNumbers copy
workflow
  .step({
    id: 'getData',
    execute: async ({ context }) => {
      return {
        data: { id: '123', value: 'example' }
      };
    }
  })
  .step({
    id: 'processData',
    execute: async ({ context }) => {
      // Access data from previous step through context.steps
      const previousData = context.steps.getData.output.data;
      // Process previousData.id and previousData.value
    }
  });
```

The context object:
- Contains results from all completed steps in `context.steps`
- Provides access to step outputs through `context.steps.[stepId].output`
- Is typed based on step output schemas
- Is immutable to ensure data consistency

## Related Documentation ✅

- [Step](./step-class.mdx)
- [.then()](./then.mdx)
- [.step()](./step-function.mdx)
- [.after()](./after.mdx)
